package com.dy.user.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dy.user.mapper.UserMapper;
import com.dy.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dy.util.SMSUtils;
import com.dy.util.TokenUtil;
import com.kaoshi.common.config.Result;
import com.dy.user.User;
import com.kaoshi.common.util.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-11-18
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    RedisTemplate redisTemplate;

    //登陆
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result login(User user) {
        Object verificationCode = redisTemplate.opsForValue().get(user.getPhone());
        System.out.println(verificationCode);
        try {
            verificationCode = Integer.parseInt(verificationCode.toString());
        } catch (Exception e) {
            return Result.fail("未获取验证码");
        }
        if (user.getNum().equals(verificationCode)) {
            User one = null;
            try {
                LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
                if (user.getPhone() != null) {
                    userLambdaQueryWrapper.eq(User::getPhone, user.getPhone());
                }
                one = baseMapper.selectOne(userLambdaQueryWrapper);
                if (one.getDisable() == 0) {
                    one.setStatus(1);
                    StpUtil.login(one.getId());
                    redisTemplate.delete(user.getPhone());
                    redisTemplate.opsForValue().set(JSONObject.toJSONString(one.getId()), JSONObject.toJSONString(one), 10, TimeUnit.DAYS);
                    redisTemplate.opsForValue().set("token", JSONObject.toJSONString(StpUtil.getTokenInfo().getTokenValue()), 10, TimeUnit.DAYS);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
                    jsonObject.put("user", one.getId());
                    return Result.ok(jsonObject);
                }
                return Result.fail("账号已被禁用");
            } catch (Exception e) {
                String uuid = UUID.randomUUID().toString().replace("-", "");
                String shortenedUuid = uuid.substring(0, 10);
                user.setName("dy" + shortenedUuid);
                user.setNumber("douyin" + shortenedUuid);
                baseMapper.insert(user);
                User user1 = baseMapper.selectOne(new LambdaQueryWrapper<>(user).eq(User::getName, user.getName()));
                StpUtil.login(user1.getId());
                redisTemplate.delete(user.getPhone());
                redisTemplate.opsForValue().set(JSONObject.toJSONString(user.getId()), JSONObject.toJSONString(user), 10, TimeUnit.DAYS);
                redisTemplate.opsForValue().set("token", JSONObject.toJSONString(StpUtil.getTokenInfo().getTokenValue()), 10, TimeUnit.DAYS);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
                jsonObject.put("user", user.getId());
                return Result.ok(jsonObject);
            }
        }
        return Result.fail("验证码错误");
    }

    //账号修改
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object updateUser(User user, HttpServletResponse response) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        User user2 = baseMapper.selectOne(userLambdaQueryWrapper.eq(User::getPhone, user.getPhone()));
        if (user2.getPassword().equals(user.getPassword())) {
            response.setStatus(400);
            return Result.build("", 400, "密码不能与原密码相同");
        }
        if (user.getId() != null) {
            userLambdaQueryWrapper.eq(User::getId, user.getId());
        }
        if (user.getPhone() != null) {
            userLambdaQueryWrapper.eq(User::getPhone, user.getPhone());
        }
        user.setPassword(MD5.encrypt(user.getPassword()));
        baseMapper.update(user, userLambdaQueryWrapper);
        redisTemplate.opsForValue().set(JSONObject.toJSONString(user.getId()), JSONObject.toJSONString(user), 10, TimeUnit.DAYS);
        StpUtil.login(user.getId());
        return Result.ok("修改成功");
    }

    //一键登录
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result loginRedis(String token) {
        Object loginIdByToken = StpUtil.getLoginIdByToken(token);
        int userid = Integer.parseInt(loginIdByToken.toString());
        Object user = redisTemplate.opsForValue().get(JSONObject.toJSONString(userid));
        if (user == null){
            User selectById = baseMapper.selectById(userid);
            if (selectById == null) {
                return Result.fail("未检测到相应的账号");
            }
            StpUtil.login(selectById.getId());
            if (selectById.getDisable() != 0) {
                return Result.fail("账号已被锁定，无法进行登陆");
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
            jsonObject.put("user", selectById.getId());
            System.out.println(jsonObject);
            return Result.ok(jsonObject);
        }
        User user1 = JSONObject.parseObject(user.toString(), User.class);
        if (user1 == null){
            return Result.fail("未检测到相应的账号");
        }
        if (user1.getDisable() != 0) {
            return Result.fail("账号已被锁定，无法进行登陆");
        }
        user1.setStatus(1);
        StpUtil.login(userid);
        redisTemplate.opsForValue().set("token", JSONObject.toJSONString(StpUtil.getTokenInfo().getTokenValue()), 10, TimeUnit.DAYS);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
        jsonObject.put("user", user1.getId());
        System.out.println(jsonObject);
        return Result.ok(jsonObject);
    }

    //短信发送
    @Override
    public void verification(User user) throws Exception {
        System.out.println(user.getPhone());
        int num = new Random().nextInt(999999 - 100000 + 1) + 100000;
//        Client client = SMSUtils.createClient();
//        SendSmsRequest sendSmsRequest = new SendSmsRequest()
//                .setSignName("抖音验证码")
//                .setTemplateCode("SMS_475350602")
//                .setPhoneNumbers("13718142658")
//                .setTemplateParam("{\"code\":\"" + num + "\"}");
//        RuntimeOptions runtime = new RuntimeOptions();
//        try {
//            client.sendSmsWithOptions(sendSmsRequest, runtime);
//        } catch (TeaException error) {
//            // 错误 message
//            System.out.println(error.getMessage());
//            // 诊断地址
//            System.out.println(error.getData().get("Recommend"));
//            com.aliyun.teautil.Common.assertAsString(error.message);
//        } catch (Exception _error) {
//            TeaException error = new TeaException(_error.getMessage(), _error);
//            // 错误 message
//            System.out.println(error.getMessage());
//            // 诊断地址
//            System.out.println(error.getData().get("Recommend"));
//            com.aliyun.teautil.Common.assertAsString(error.message);
//        }
        redisTemplate.opsForValue().set(user.getPhone(), JSONObject.toJSONString(num), 10, TimeUnit.MINUTES);
    }

    //重置密码
    @Override
    public Result resetpassword(User user) {
        if (user.getNewpassword() == null) {
            return Result.fail("新密码不能为空");
        }
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getPhone, user.getPhone());
        User user1 = baseMapper.selectOne(userLambdaQueryWrapper);
        if (user1 == null) {
            return Result.fail("手机号或密码错误");
        }
        if (user.getNewpassword().equals(user1.getPassword())) {
            return Result.fail("新密码不能与旧密码相同");
        }
        user1.setPassword(MD5.encrypt(user.getNewpassword()));
        baseMapper.updateById(user1);
        return Result.ok("修改成功,请重新登录吧");
    }

    //密码登录
    @Override
    public Result passwordLogin(User user) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getPhone, user.getPhone());
        user.setPassword(MD5.encrypt(user.getPassword()));
        userLambdaQueryWrapper.eq(User::getPassword, user.getPassword());
        User user1 = baseMapper.selectOne(userLambdaQueryWrapper);
        if (user1 == null) {
            return Result.fail("手机号或密码错误");
        }
        user1.setStatus(1);
        StpUtil.login(user1.getId());
        redisTemplate.opsForValue().set(JSONObject.toJSONString(user.getId()), JSONObject.toJSONString(user), 10, TimeUnit.DAYS);
        redisTemplate.opsForValue().set("token", JSONObject.toJSONString(StpUtil.getTokenInfo().getTokenValue()), 10, TimeUnit.DAYS);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
        jsonObject.put("user", user1.getId());
        return Result.ok(jsonObject);
    }

    //账号修改密码认证
    @Override
    public Result sendSms(User user) {
        User user1 = baseMapper.selectOne(new LambdaQueryWrapper<>(user).eq(User::getPhone, user.getPhone()));
        if (user1 == null) {
            return Result.fail("手机号不存在");
        }
        Object verificationCode = redisTemplate.opsForValue().get(user.getPhone());
        int i = Integer.parseInt(verificationCode.toString());
        if (i != user.getNum()) {
            return Result.fail("验证码错误");
        }
        return Result.ok("验证码发送成功");
    }

    //账号禁用
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result disableUser(User user, String token) {
        //查询登陆人账号数据
        Object loginIdByToken = StpUtil.getLoginIdByToken(token);
        if (loginIdByToken == null){
            return Result.fail("您未进行过登录");
        }
        //登陆人id
        int parseInt = Integer.parseInt(loginIdByToken.toString());
        Object o = redisTemplate.opsForValue().get(parseInt);

        if(o == null){
            //查询数据库账号数据
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userLambdaQueryWrapper.eq(User::getPhone, user.getPhone().trim());
            User user1 = baseMapper.selectOne(userLambdaQueryWrapper);
            if (user1 == null) {
                return Result.fail("账号不存在");
            }
            User selectById = baseMapper.selectById(parseInt);
            //判断是否为登陆人
            if (selectById.getPhone().equals(user1.getPhone())) {
                //账号封禁逻辑
                user1.setDisable(1);
                user1.setStatus(0);
                StpUtil.logout(parseInt);
                StpUtil.kickout(parseInt);
                StpUtil.disable(user1.getId(), -1);
                baseMapper.updateById(user1);
                return Result.ok("锁定成功");
            }
            return Result.fail("您没有权限锁定该账号");
        }
        //redis数据中的用户数据
        User user1 = JSONObject.parseObject(o.toString(), User.class);
        if (user1 == null) {
            return Result.fail("账号不存在");
        }
        //判断是否为登陆人
        if (user1.getPhone().equals(user.getPhone())) {
            //账号封禁逻辑
            user1.setDisable(1);
            user1.setStatus(0);
            StpUtil.logout(parseInt);
            StpUtil.kickout(parseInt);
            StpUtil.disable(user1.getId(), -1);
            baseMapper.updateById(user1);
            return Result.ok("锁定成功");
        }
        return Result.fail("您没有权限锁定该账号");
    }

    //账号解禁
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateDisable(User user) {
        Object verificationCode = redisTemplate.opsForValue().get(user.getPhone());
        if (verificationCode == null) {
            return Result.fail("请输入正确验证码");
        }

        int yzm = Integer.parseInt(verificationCode.toString());
        if (yzm != user.getNum()) {
            return Result.fail("验证码错误");
        }

        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getPhone, user.getPhone());
        //md5加密
        user.setPassword(MD5.encrypt(user.getPassword()));
        //密码验证
        userLambdaQueryWrapper.eq(User::getPassword, user.getPassword());
        User user1 = baseMapper.selectOne(userLambdaQueryWrapper);
        if (user1 == null) {
            return Result.fail("手机号或密码错误");
        }
        if (user1.getDisable() == 0){
            return Result.fail("账号状态正常无需解除锁定");
        }

        user1.setDisable(0);
        StpUtil.login(user1.getId());
        StpUtil.untieDisable(user1.getId());
        baseMapper.updateById(user1);
        return Result.ok(user1);
    }

    //一键登录账号检测
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result logout(String token) {
        Object loginIdByToken = StpUtil.getLoginIdByToken(token);
        if (loginIdByToken == null) {
            return Result.fail("账号未登录");
        }
        JSONObject jsonObject = new JSONObject();
        Object o = redisTemplate.opsForValue().get(JSONObject.toJSONString(Integer.parseInt(loginIdByToken.toString())));
        User selectById = null;
        if (o == null){
            selectById = baseMapper.selectById(Integer.parseInt(loginIdByToken.toString()));
            jsonObject.put("phone", selectById.getPhone());
        }else {
            User user = JSONObject.parseObject(o.toString(), User.class);
            jsonObject.put("phone", user.getPhone());
        }
        jsonObject.put("tokenName", token);
        return Result.ok(jsonObject);
    }

    @Override
    public int getUserByToken(String token) {
        Object loginIdByToken = StpUtil.getLoginIdByToken(token);
        return baseMapper.selectById(Integer.parseInt(loginIdByToken.toString())).getId();
    }

    @Override
    public User getLoginUser(String satoken) {
        if (StpUtil.isLogin()){
            Object loginIdByToken = StpUtil.getLoginIdByToken(satoken);
            return baseMapper.selectById(Integer.parseInt(loginIdByToken.toString()));
        }
        System.out.println("先登陆再查，没登陆你查个屁！！！");
        return null;
    }

    //钉钉登录
    @Override
    public Result getDingUser(User user) {
        User sqluser = baseMapper.selectOne(new LambdaQueryWrapper<>(user).eq(User::getName, user.getName()).eq(User::getPhone, user.getPhone()));
        if (sqluser == null){
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String shortenedUuid = uuid.substring(0, 10);
            user.setNumber("douyin" + shortenedUuid);
            baseMapper.insert(user);
            user.setStatus(1);
            StpUtil.login(user.getId());
            redisTemplate.opsForValue().set(JSONObject.toJSONString(user.getId()), JSONObject.toJSONString(user), 10, TimeUnit.DAYS);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
            jsonObject.put("user",sqluser.getId());
            return Result.ok(jsonObject);
        }
        sqluser.setStatus(1);
        StpUtil.login(sqluser.getId());
        redisTemplate.opsForValue().set(JSONObject.toJSONString(sqluser.getId()), JSONObject.toJSONString(sqluser), 10, TimeUnit.DAYS);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("satoken", StpUtil.getTokenInfo().getTokenValue());
        jsonObject.put("user",sqluser.getId());
        return Result.ok(jsonObject);
    }

    @Override
    public User getUserById(int id) {
        return baseMapper.selectById(id);
    }

    @Override
    public User selectUserById(Integer id) {
        return baseMapper.selectById(id);
    }

    @Override
    public Result outLogin(Integer id) {
        User user = baseMapper.selectById(id);
        user.setStatus(0);
        redisTemplate.delete(JSONObject.toJSONString(user.getId()));
        StpUtil.logout(user.getId());
        return Result.ok();
    }


}
